Swift ConcurrencyとNEHotspotConfigurationでシンプルなWi-Fi接続を実装する

Swift ConcurrencyとNEHotspotConfigurationでシンプルなWi-Fi接続を実装する

Clock Icon2024.06.24

Nintendo Switchには撮影したスクリーンショットを「スマートフォンに送る」という機能がある。この機能は、表示されているQRコードをスマートフォンで読み取り、Nintendo Switchが作成したWi-Fiネットワークに接続してスクリーンショットをダウンロードするという手順で動作する。現在開発中のアプリでは、この一連の手作業を自動化することを目指している。

この自動化を実現するために、iOS 11から導入されたNEHotspotConfigurationNEHotspotConfigurationManagerを使用する。これらのAPIを使用することで、アプリから動的にWi-Fi接続の制御ができる。

NEHotspotConfigurationNEHotspotConfigurationManagerの基本的な使い方については、以下の記事でSINさんが詳しく解説しているので参照してほしい。

https://dev.classmethod.jp/articles/nehotspotconfiguration/

本記事では、Swift Concurrencyを活用してより簡潔にWi-Fiホットスポットへの接続を実装する方法を紹介する。

iOSアプリから特定のWi-Fiネットワークに接続する

iOSアプリから特定のWi-Fiネットワークに接続する方法は以下の通り。

1. NEHotspotConfigurationの設定

指定されたSSIDおよびパスフレーズを使ってWi-Fiネットワークに接続する。

この関数では、NEHotspotConfigurationを作成し、それをNEHotspotConfigurationManagerを通じて適用する。パスワードが提供されている場合は、WPA/WPA2用の設定を作成し、そうでない場合はオープンネットワークの設定を作成する。

Swift ConcurrencyのwithCheckedThrowingContinuationを使って非同期のエラー処理を行う。これにより、NEHotspotConfigurationManagerapplyメソッドの完了ハンドラーを非同期に処理できる。

private func connectToWiFi(ssidName: String, passphrase: String?) async throws {
    let configuration: NEHotspotConfiguration
    if let passphrase = passphrase {
        configuration = NEHotspotConfiguration(ssid: ssidName, passphrase: passphrase, isWEP: false)
    } else {
        configuration = NEHotspotConfiguration(ssid: ssidName)
    }

    try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
        NEHotspotConfigurationManager.shared.apply(configuration) { error in
            if let error = error {
                continuation.resume(throwing: error)
            } else {
                continuation.resume(returning: ())
            }
        }
    }
}

NEHotspotConfigurationErrorのエラーリスト

Wi-Fiの接続時になんらかの問題が発生するとエラーが投げられる。この関数から投げられるエラー NEHotspotConfigurationError は下表の通り。エラーに関する詳細な説明はこちらを参照してほしい。

エラー 説明
invalid 無効な設定
invalidSSID 無効なSSID
invalidWPAPassphrase 無効なWPAパスフレーズ
invalidWEPPassphrase 無効なWEPパスフレーズ
invalidEAPSettings 無効なEAP設定
invalidHS20Settings 無効なHS20設定
invalidHS20DomainName 無効なHS20ドメイン名
userDenied ユーザーが許可しなかった
internal 内部エラーが発生した

接続ダイアログでキャンセルをクリックすると userDenied エラーが投げられる。他のエラーと異なりユーザーが自身で選択して発生させたエラーのため、エラーダイアログを表示させないなどの工夫をすることでユーザーにとって使いやすいアプリになるだろう。

do {
    try await connectToWiFi(ssidName: "ssid name", passphrase: "passphrase")
} catch NEHotspotConfigurationError.userDenied {
    // ユーザーがキャンセルした場合の処理
    print("ユーザーが接続をキャンセルしました")
} catch {
    // その他のエラー処理
    print("エラーが発生しました: \(error)")
}

2. Wi-Fiへの接続

上記のconnectToWiFi関数を利用して、特定のSSIDに接続するには、以下のようにパラメータを指定して実行する。

try await connectToWiFi(ssidName: "ssid name", passphrase: "passphrase")

3. ホットスポット構成の削除

特定のSSIDの構成を削除するには、以下のようにremoveConfigurationを実行する。

NEHotspotConfigurationManager.shared.removeConfiguration(forSSID: "ssid name")

Wi-Fi接続情報のQRコードフォーマット

Wi-Fiネットワークの設定をQRコードで提供する場合のフォーマットはある程度規格化されているようだ。以下のような形式のQRコードをスキャンすると、デバイスをWi-Fiネットワークに接続できる。詳細はこちらを参照。

例: WIFI:T:WPA;S:mynetwork;P:mypass;H:false;;

フォーマット例:

  • WPA/WPA2 Personal: WIFI:T:WPA;S:MyNetwork;P:mypassword;H:false;;
  • WEP: WIFI:T:WEP;S:MyNetwork;P:mypassword;H:false;;
  • オープンネットワーク: WIFI:T:nopass;S:MyOpenNetwork;H:false;;

各パラメータの説明

パラメータ 説明
T 認証タイプ(例: WPA, WEP, WPA2-EAP, nopass)
S SSID(ネットワーク名)
P パスワード(認証タイプがnopassの場合は省略可能)
H 隠しSSIDかどうか(trueまたはfalse)
E EAPメソッド(WPA2-EAPの場合のみ)
A 匿名ID(WPA2-EAPの場合のみ)
I ID(WPA2-EAPの場合のみ)
PH2 フェーズ2メソッド(WPA2-EAPの場合のみ)

まとめ

NEHotspotConfigurationとNEHotspotConfigurationManagerを使うことで、アプリ内から簡単にWi-Fiネットワークへの接続と切断を管理できる。Swift Concurrencyを利用することで、非同期操作がさらに簡単にできるようになった。

参考文献

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.